https://www.iteye.com/topic/336577
//“愿中国的年轻人都摆脱冷气，只是向上走，不必听自暴自弃者的话，能做事的做事，能发声的发声。有一分热，发一份光，就如萤火虫一般，也可以在黑暗中里发一点光，不必等待炬火！”

/**
* 构建DFA屏蔽字map
* js 实现
*/

function makeSensitiveMap() 
{
    let sensitiveWordList = GameData.GetConfigForName("sensitiveWords");
    // 构造根节点
    
    const result = new Map();
    for (let j = 0; j < sensitiveWordList.length; ++j) 
    {
        let word = sensitiveWordList[j].words;
        let map = result;
        for (let i = 0; i < word.length; i++) 
        {
        // 依次获取字
            const char = word.charAt(i);
        // 判断是否存在
            if (map.get(char)) 
            {
        // 获取下一层节点
                map = map.get(char);
            } 
            else 
            {
                // 将当前节点设置为非结尾节点
                // if (map.get('laster') === true) 
                // {
                //     map.set('laster', false);
                // }
                const item = new Map();
                // 新增节点默认为结尾节点
                item.set('laster', i == (word.length - 1));
                map.set(char, item);
                map = map.get(char);
            }
        }
    }
    GameData.s_sensitiveMap = result;
    //console.log(GameData.s_sensitiveMap);
    return result;
}

//将敏感词替换为*
function filterSensitiveWord(txt) 
{
    let matchResult = { flag: false, sensitiveWord: '' };
    // 过滤掉除了中文、英文、数字之外的
    let txtTrim = txt.replace(/[^\u4e00-\u9fa5\u0030-\u0039\u0061-\u007a\u0041-\u005a]+/g, '');
    for (let i = 0; i < txtTrim.length; i++) {
        matchResult = Utils.checkSensitiveWord(GameData.s_sensitiveMap, txtTrim, i);
        if (matchResult.flag) {
            //现在需要把这些敏感词替换成*
            let tempStr = "";
            for(let i = 0 ; i < matchResult.sensitiveWord.length; ++i)
            {
                tempStr = tempStr + "*";
            }
            txtTrim = txtTrim.replace(matchResult.sensitiveWord,tempStr);                
            //console.log(`sensitiveWord:${matchResult.sensitiveWord}`);
            //break;
        }
    }
    return txtTrim;
}

    /**
    * @description
    * 检查敏感词是否存在
    * @private
    * @param {any} txt
    * @param {any} index
    * @returns
    */
   function checkSensitiveWord(sensitiveMap, txt, index) 
   {
       let currentMap = sensitiveMap;
       let flag = false;
       let wordNum = 0;//记录过滤
       let sensitiveWord = ''; //记录过滤出来的敏感词
       for (let i = index; i < txt.length; i++) 
       {
           const word = txt.charAt(i);
           currentMap = currentMap.get(word);
           if (currentMap) 
           {
               wordNum++;
               sensitiveWord += word;
               if (currentMap.get('laster') === true) 
               {
                   // 表示已到词的结尾
                   flag = true;
                   break;
               }
           }
           else 
           {
               break;
           }
       }
       // 两字成词
       //console.log("############",wordNum,flag,sensitiveWord);
       // if (wordNum < 2) 
       // {
       //     flag = false;
       // }
       return { flag, sensitiveWord };
   }

   function isHaveSensitiveWord(txt):boolean
   {
       let matchResult = { flag: false, sensitiveWord: '' };
       // 过滤掉除了中文、英文、数字之外的
       //const txtTrim = txt.replace(/[^\u4e00-\u9fa5\u0030-\u0039\u0061-\u007a\u0041-\u005a]+/g, '');
       const txtTrim = txt;
       for (let i = 0; i < txtTrim.length; i++) 
       {
           matchResult = Utils.checkSensitiveWord(GameData.s_sensitiveMap, txtTrim, i);
           if (matchResult.flag) 
           {
               //console.log(`sensitiveWord:${matchResult.sensitiveWord}`);
               break;
           }
       }
       return matchResult.flag;
   }